import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/learning_content/learning_locale.dart';

part 'cefr_level.dart';

part 'dialect.dart';

part 'lexical_item_use_case.dart';

part 'word_tags.dart';

sealed class LexicalItem {
  String get id;

  String get title;

  BuiltMap<Dialect, String> get transcriptions;

  BuiltMap<LearningLocale, String> get translations;

  String get definition;

  BuiltList<LexicalItemUseCase> get useCases;

  String? get imageId;

  LexicalItem copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<Dialect, String> Function()? transcriptions,
    BuiltMap<LearningLocale, String> Function()? translations,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
  });
}

sealed class Word implements LexicalItem {
  int? get rank;

  WordTags get tags;

  @override
  Word copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<Dialect, String> Function()? transcriptions,
    BuiltMap<LearningLocale, String> Function()? translations,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  });
}

class UnspecifiedWord extends Equatable implements Word {
  const UnspecifiedWord({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  UnspecifiedWord copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return UnspecifiedWord(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Adjective extends Equatable implements Word {
  const Adjective({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Adjective copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Adjective(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Adverb extends Equatable implements Word {
  const Adverb({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Adverb copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Adverb(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Conjunction extends Equatable implements Word {
  const Conjunction({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Conjunction copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Conjunction(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Noun extends Equatable implements Word {
  const Noun({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Noun copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Noun(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Numeral extends Equatable implements Word {
  const Numeral({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Numeral copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Numeral(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Preposition extends Equatable implements Word {
  const Preposition({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Preposition copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Preposition(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Pronoun extends Equatable implements Word {
  const Pronoun({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Pronoun copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Pronoun(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class Verb extends Equatable implements Word {
  const Verb({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
    required this.tags,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final WordTags tags;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
      tags,
    ];
  }

  @override
  Verb copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
    WordTags Function()? tags,
  }) {
    return Verb(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
      tags: tags == null ? this.tags : tags(),
    );
  }
}

class PhrasalVerb extends Equatable implements LexicalItem {
  const PhrasalVerb({
    required this.id,
    required this.title,
    required this.translations,
    required this.transcriptions,
    required this.definition,
    required this.useCases,
    required this.imageId,
    required this.rank,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<LearningLocale, String> translations;

  @override
  final BuiltMap<Dialect, String> transcriptions;

  @override
  final String definition;

  @override
  final BuiltList<LexicalItemUseCase> useCases;

  @override
  final String? imageId;

  final int? rank;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translations,
      transcriptions,
      definition,
      useCases,
      imageId,
      rank,
    ];
  }

  @override
  PhrasalVerb copyWith({
    String Function()? id,
    String Function()? title,
    BuiltMap<LearningLocale, String> Function()? translations,
    BuiltMap<Dialect, String> Function()? transcriptions,
    String Function()? definition,
    BuiltList<LexicalItemUseCase> Function()? useCases,
    String? Function()? imageId,
    int? Function()? rank,
  }) {
    return PhrasalVerb(
      id: id == null ? this.id : id(),
      title: title == null ? this.title : title(),
      translations: translations == null ? this.translations : translations(),
      transcriptions: transcriptions == null ? this.transcriptions : transcriptions(),
      definition: definition == null ? this.definition : definition(),
      useCases: useCases == null ? this.useCases : useCases(),
      imageId: imageId == null ? this.imageId : imageId(),
      rank: rank == null ? this.rank : rank(),
    );
  }
}
